using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing.Drawing2D;
//using ITSystemeConfigTool.Properties;
using System.IO;
using System.Drawing.Imaging;
// BEGIN: j.ulbrich
using System.Xml;
using System.Xml.Schema;
// END: j.ulbrich

namespace OpenComposite.EII.XSDEditor
{
    public class MakeXSDfromTV
    {
        #region Constant Fields

        private const int _ICON_CATEGORYCLOSE = 0;
        private const int _ICON_CATEGORYOPEN = 1;
        private const int _ICON_GROUP = 2;
        private const int _ICON_COMPUTER = 3;
        private const int _ICON_FIELD = 4;

        private const int _TYPE_DOMAIN = 0;
        private const int _TYPE_SYSTEM = 0;
        private const int _TYPE_GLOSSARVARIABLE = 0;
        private const int _TYPE_CATEGORY = 1;
        private const int _TYPE_CHOICE = 2;
        private const int _TYPE_GROUP = 3;
        private const int _TYPE_SIMPLETYPE = 4;
        private const int _TYPE_ATTRIBUTE = 5;
        private const int _TYPE_ATTRIBUTEGROUP = 6;

        private const string _IO_INPUT = "i";
        private const string _IO_OUTPUT = "o";

        private const string _GLOSSAR_ROOT = "Glossar";

        private const string _CANONICAL_XMLNS = "http://www.theopencomposite.com/canonical_document";

        #endregion

        public MakeXSDfromTV()
        { 
        }

        public XmlDocument GenerateXSDfromTV(TreeView tv)
        {
            XmlSchema schema = new XmlSchema();
            schema.Namespaces.Add("", _CANONICAL_XMLNS);
            schema.TargetNamespace = _CANONICAL_XMLNS;
            
            XmlSchemaElement xselRoot = new XmlSchemaElement();
            xselRoot.Name = tv.Nodes[0].Text; ;
            schema.Items.Add(xselRoot);

            //// Test AttributeGroup
            //XmlSchemaAttributeGroup ag = new XmlSchemaAttributeGroup();
            //ag.Name = "myAttributeGroup";
            //schema.Items.Add(ag);
            //// Ende: Test AttributeGroup

            //// Test Group
            //XmlSchemaGroup gr = new XmlSchemaGroup();
            //schema.Items.Add(gr);
            //gr.Name = "myGroup";

            //XmlSchemaSequence s = new XmlSchemaSequence();
            //gr.Particle = s;
            //// Test Group
            
            XmlSchemaComplexType ctRoot = new XmlSchemaComplexType();
            xselRoot.SchemaType = ctRoot;
            //schema.Items.Add(ctRoot);
            //ctRoot.Name = "Header";
            XmlSchemaSequence seqRoot = new XmlSchemaSequence();
            ctRoot.Particle = seqRoot;

            // create Header-element
            //XmlSchemaElement header = new XmlSchemaElement();
            //header.Name = "Header";
            //seqRoot.Items.Add(header);
            //XmlSchemaComplexType headerRoot = new XmlSchemaComplexType();
            //header.SchemaType = headerRoot;
            //XmlSchemaSequence seqHeader = new XmlSchemaSequence();
            //headerRoot.Particle = seqHeader;

            //XmlSchemaElement DocGUID = new XmlSchemaElement();
            //seqHeader.Items.Add(DocGUID);
            //DocGUID.Name = "DocGUID";
            //DocGUID.SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

            //XmlSchemaElement Publisher = new XmlSchemaElement();
            //seqHeader.Items.Add(Publisher);
            //Publisher.Name = "Publisher";
            //Publisher.SchemaTypeName = new XmlQualifiedName("string", "http://www.w3.org/2001/XMLSchema");

            // generate xsd for all child nodes
            //foreach (TreeNode tnChild in treeGlossar.Nodes[0].Nodes)
            foreach (TreeNode tnChild in tv.Nodes[0].Nodes)
            {
                XmlSchemaObject xsobj = generateXSDRecursive(tnChild);
                if (xsobj is XmlSchemaAttribute)
                    ctRoot.Attributes.Add(xsobj);
                else
                    seqRoot.Items.Add(generateXSDRecursive(tnChild));
            }

            //// Test Group
            //XmlSchemaGroup gr = new XmlSchemaGroup();
            //seqRoot.Items.Add(gr);
            //gr.Name = "myGroup";

            //XmlSchemaSequence s = new XmlSchemaSequence();
            //gr.Particle = s;
            //// Test Group

            //// Test AttributeGroup
            //XmlSchemaAttributeGroup ag = new XmlSchemaAttributeGroup();
            //ag.Name = "myAttributeGroup";
            //seqRoot.Items.Add(ag);
            //// Ende: Test AttributeGroup


            XmlSchemaSet schemaSet = new XmlSchemaSet();
            schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallbackOne);
            schemaSet.Add(schema);
            schemaSet.Compile();

            XmlSchema compiledSchema = new XmlSchema();

            foreach (XmlSchema schema1 in schemaSet.Schemas())
            {
                compiledSchema = schema1;
            }

            XmlDocument xd = new XmlDocument();
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
            nsmgr.AddNamespace("xs", "http://www.w3.org/2001/XMLSchema");
            nsmgr.AddNamespace("", _CANONICAL_XMLNS);
            using (StringWriter sw = new StringWriter())
            {
                compiledSchema.Write(sw, nsmgr);
                xd.LoadXml(sw.ToString());
                //Debug.WriteLine(sw.ToString());
            }

            //formXmlViewer dlg = new formXmlViewer();
            //dlg.XmlDocument = xd;
            //dlg.ShowDialog();

            return xd;
        }

        //private object CreateSchemaElementOrSchemaGroup(ITSystemsConfig.glossar_variablesRow row)
        //{
        //    object oRet = null;
        //    if (row.gvariabletype == _TYPE_GROUP)
        //        oRet = new XmlSchemaGroup();
        //    else
        //        oRet = new XmlSchemaElement();

        //    return oRet;
        //}
        //private XmlSchemaAttributeGroup CreateXmlAtrributeGroup(TreeNode tn)
        //{
        //    XmlSchemaAttributeGroup ag = new XmlSchemaAttributeGroup();
        //    foreach (TreeNode tnChild in tn.Nodes)
        //        ag.Attributes.Add(generateXSDRecursive(tnChild));

        //    return ag;
        //}

        //private /*XmlSchemaElement*/ XmlSchemaObject generateXSDRecursive(TreeNode tn)
        //{
        //    // get glossar variable row from tree node tag
        //    ITSystemsConfig.glossar_variablesRow row = tn.Tag as ITSystemsConfig.glossar_variablesRow;
        //    if (row == null)
        //        throw new NullReferenceException("TreeNode.Tag is null.");

        //    // create schema element for the current glossar variable
        //    XmlSchemaElement elem = new XmlSchemaElement();


        //    elem.Name = row.gvariablename;

        //    if (row.minOccurs != DBNull.Value.ToString())
        //    {
        //        elem.MinOccursString = row.minOccurs;
        //    }
        //    if (row.maxOccurs != DBNull.Value.ToString())
        //    {
        //        elem.MaxOccursString = row.maxOccurs;
        //    }

        //    // if current tree node has children
        //    if (tn.Nodes.Count > 0)
        //    {
        //        // create complexType element
        //        XmlSchemaComplexType ct = new XmlSchemaComplexType();
        //        elem.SchemaType = ct;



        //        // create sequence element
        //        XmlSchemaSequence seq = new XmlSchemaSequence();
        //        ct.Particle = seq;

        //        //// create group element
        //        //if (row.gvariabletype == _TYPE_GROUP)
        //        //{
        //        //    XmlSchemaGroup ge = new XmlSchemaGroup();
        //        //    seq.Items.Add(ge);
        //        //}

        //        // generate xsd for all child nodes
        //        foreach (TreeNode tnChild in tn.Nodes)
        //        {
        //            XmlSchemaObject xsobj = generateXSDRecursive(tnChild);
        //            if (xsobj is XmlSchemaAttribute || xsobj is XmlSchemaSimpleType)
        //                ct.Attributes.Add(xsobj);
        //            else
        //                seq.Items.Add(xsobj);
        //        }
                

        //        // create choice element
        //        if (row.gvariabletype == _TYPE_CHOICE)
        //        {
        //            XmlSchemaChoice ch = new XmlSchemaChoice();
        //            ct.Particle = ch;

        //            foreach (TreeNode tnChild in tn.Nodes)
        //            {
        //                ch.Items.Add(generateXSDRecursive(tnChild));
        //            }
        //        }


        //    }
        //    else if (row.gvariabletype == _TYPE_GLOSSARVARIABLE)
        //    {
        //        // if current tree node has no children and gvariabletype is _TYPE_GLOSSARVARIABLE
        //        //    -> this is a simple type

        //        // set schema type name
        //        elem.SchemaTypeName = new XmlQualifiedName(row.gdatatype, "http://www.w3.org/2001/XMLSchema");
        //    }
        //    // Aufnahme von SimpleType
        //    //else if (row.gvariabletype == _TYPE_SIMPLETYPE)
        //    //{
        //    //    XmlSchemaSimpleType st = new XmlSchemaSimpleType();
        //    //    st.Name = row.gvariablename;
        //    //    //st.DerivedBy = XmlSchemaDerivationMethod.All.
                
        //    //    //st.SchemaTypeName = new XmlQualifiedName(row.gdatatype, "http://www.w3.org/2001/XMLSchema");
        //    //    return st;
        //    //}
        //    // END: Aufnahme von SimpleType

        //    // return new schema element
        //    return elem;
        //}

        private XmlSchemaObject generateXSDRecursive(TreeNode tn)
        {
            // get glossar variable row from tree node tag
            if (tn.Tag is XmlSchemaElement)
            {
                XmlSchemaElement row = tn.Tag as XmlSchemaElement;
            }
            if (tn.Tag is XmlSchemaComplexType)
            {
                XmlSchemaComplexType row = tn.Tag as XmlSchemaComplexType;
            }
            if (tn.Tag == null)
                throw new NullReferenceException("TreeNode.Tag is null.");

            // create schema element for the current glossar variable
            XmlSchemaElement elem = new XmlSchemaElement();


            elem.Name = tn.Text;

            //if (row.minOccurs != DBNull.Value.ToString())
            //{
            //    elem.MinOccursString = row.minOccurs;
            //}
            //if (row.maxOccurs != DBNull.Value.ToString())
            //{
            //    elem.MaxOccursString = row.maxOccurs;
            //}

            // if current tree node has children
            if (tn.Nodes.Count > 0)
            {
                // create complexType element
                XmlSchemaComplexType ct = new XmlSchemaComplexType();
                elem.SchemaType = ct;
                
                // create sequence element
                XmlSchemaSequence seq = new XmlSchemaSequence();
                ct.Particle = seq;
                
                // generate xsd for all child nodes
                foreach (TreeNode tnChild in tn.Nodes)
                {
                    XmlSchemaObject xsobj = generateXSDRecursive(tnChild);
                    if (xsobj is XmlSchemaAttribute)
                        ct.Attributes.Add(xsobj);
                    //else if (xsobj is XmlSchemaAttributeGroup)
                    //    return CreateXmlAtrributeGroup(tnChild);
                    else
                        seq.Items.Add(xsobj);
                }

                // create choice element

                //if (row.gvariabletype == _TYPE_CHOICE)
                //{
                //    XmlSchemaChoice ch = new XmlSchemaChoice();
                //    ct.Particle = ch;

                //    foreach (TreeNode tnChild in tn.Nodes)
                //    {
                //        ch.Items.Add(generateXSDRecursive(tnChild));
                //    }
                //}
                // create Attribute Group element
                //if (row.gvariabletype == _TYPE_ATTRIBUTEGROUP)
                //{
                //    XmlSchemaAttributeGroup atgr = new XmlSchemaAttributeGroup();
                //    atgr.Name = row.gvariablename;
                //    //ct.Particle = atgr;

                //    foreach (TreeNode tnChild in tn.Nodes)
                //        atgr.Attributes.Add(generateXSDRecursive(tnChild));

                //    return atgr;
                    
                //}


            }
            else if (tn.Tag is XmlSchemaElement)
            {
                // if current tree node has no children and gvariabletype is _TYPE_GLOSSARVARIABLE
                //    -> this is a simple type

                // set schema type name
                elem.SchemaTypeName = new XmlQualifiedName((tn.Tag as XmlSchemaElement).SchemaTypeName.ToString(), "http://www.w3.org/2001/XMLSchema");
            }
            // Aufnahme von Attribute
            //else if (row.gvariabletype == _TYPE_ATTRIBUTE)
            //{
            //    XmlSchemaAttribute at = new XmlSchemaAttribute();
            //    at.Name = row.gvariablename;
            //    at.SchemaTypeName = new XmlQualifiedName(row.gdatatype, "http://www.w3.org/2001/XMLSchema");

            //    return at;
            //}
            
            // return new schema element
            return elem;
        }

        private static void ValidationCallbackOne(object sender, ValidationEventArgs args)
        {
            //Console.WriteLine(args.Message);
            //Debug.WriteLine(args.Message);
        }
        // END: j.ulbrich

    }
}
